package com.risk.kernel.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.risk.common.core.domain.AjaxResult;
import com.risk.kernel.domain.TkCommonDbConfig;
import com.risk.kernel.domain.TkTaskCase;
import com.risk.kernel.domain.TkTaskCaseInfo;
import com.risk.kernel.domain.TkTaskCaseResult;
import com.risk.kernel.mapper.TkTaskCaseInfoMapper;
import com.risk.kernel.mapper.TkTaskCaseMapper;
import com.risk.kernel.mapper.TkTaskCaseResultMapper;
import com.risk.kernel.service.TkCommonDbConfigServiceI;
import com.risk.kernel.service.TkTaskCaseExecuteServiceI;
import com.risk.kernel.utils.*;
import com.risk.kernel.vo.TkTaskCaseInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.sql.SQLException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: Liwen
 * @createTime: 2025/1/23
 * @description:
 */
@Service
@Slf4j
public class TkTaskCaseExecuteServiceImpl implements TkTaskCaseExecuteServiceI {
    @Autowired
    private TkTaskCaseInfoMapper infoMapper;
    @Autowired
    private TkTaskCaseResultMapper caseResultMapper;
    @Autowired
    private TkTaskCaseMapper tkTaskCaseMapper;
    @Autowired
    private TkCommonDbConfigServiceI dbConfigService;

    private static String resultId = "";

    @Override
    public AjaxResult executeAdd(String caseId, String caseName) {
        // 查询测试用例集合
        List<TkTaskCaseInfo> infoList = infoMapper.selectTkTaskCaseInfoList(caseId);
        if (CollectionUtils.isEmpty(infoList)) {
            return AjaxResult.error(400, "未找到测试用例！");
        }
        resultId = RandomUtil.getRandomNumber();
        String caseNamePoke = caseName + "_Result_" + DateUtil.getCurrentDateTimeNumbers();
        updateTaskCaseStatus(caseId, 1);
        //遍历集合，执行每一行
        for (TkTaskCaseInfo tkTaskCaseInfo : infoList) {
            String actualResult = "";// 实际结果
            JSONObject execContent = JSONObject.parseObject(tkTaskCaseInfo.getExecContent());
            if (!"1".equals(execContent.get("isExecute").toString())) {
                tkTaskCaseInfo.setExecResult(2L);
                addExecuteResult(tkTaskCaseInfo, resultId, caseNamePoke);
                continue;
            }
            // 执行逻辑
            try {
//                Thread.sleep(2000);
                log.info("【开始执行用例逻辑】:{}", execContent);
                actualResult = execCaseRow(execContent);
            } catch (Exception e) {
                log.error("【用例逻辑执行失败了】,{}", execContent);
                tkTaskCaseInfo.setRemark(ExceptionUtil.handleExceptionFormat(e));
                addExecuteResult(tkTaskCaseInfo, resultId, caseNamePoke);
                updateTaskCaseStatus(caseId, 3);
                return AjaxResult.error(500, "【用例逻辑执行失败了】" + ExceptionUtil.handleExceptionFormat(e));
            }
            // 添加当前行执行成功结果
            String jsonExecContent = calculateResultWriteCase(execContent, actualResult);
            tkTaskCaseInfo.setExecResult(1L);
            tkTaskCaseInfo.setExecContent(jsonExecContent);
            addExecuteResult(tkTaskCaseInfo, resultId, caseNamePoke);
        }
        JdbcUtil.close();
        MongoUtil.closeMongoClient();
        updateTaskCaseStatus(caseId, 2);
        return AjaxResult.success("操作成功", new JSONObject().put("resultId", resultId));
    }

    /**
     * 保存执行结果到 result表
     */
    public void addExecuteResult(TkTaskCaseInfo caseInfo, String resultId, String caseName) {
        TkTaskCaseResult tkTaskCaseResult = new TkTaskCaseResult();
        tkTaskCaseResult.setResultId(resultId);
        tkTaskCaseResult.setCaseName(caseName);
        BeanUtils.copyProperties(caseInfo, tkTaskCaseResult);
        caseResultMapper.insertTkTaskCaseResult(tkTaskCaseResult);
    }

    public void updateTaskCaseStatus(String caseId, Integer status) {
        // 修改用例执行状态
        TkTaskCase tkTaskCase = tkTaskCaseMapper.selectTkTaskCaseById(caseId);
        tkTaskCase.setCaseStatus(status);
        tkTaskCaseMapper.updateTkTaskCase(tkTaskCase);
    }

    /**
     * 实时查询当前测试用例的执行结果
     *
     * @return
     */
    @Override
    public List<TkTaskCaseInfoVo> getExecuteList() {
        List<TkTaskCaseResult> list = caseResultMapper.getExecuteList(resultId);
        List<TkTaskCaseInfoVo> resultList = list.stream().map(item -> {
            TkTaskCaseInfoVo tkTaskCaseInfoVo = new TkTaskCaseInfoVo();
            BeanUtils.copyProperties(item, tkTaskCaseInfoVo);
            tkTaskCaseInfoVo.setExecContent(JSONObject.parseObject(item.getExecContent()));
            return tkTaskCaseInfoVo;
        }).collect(Collectors.toList());
        return resultList;
    }

    /**
     * 用例结果是否执行完成
     *
     * @param caseId
     * @return
     */
    @Override
    public Boolean getExecuteResultIsFinish(String caseId) {
        Integer infoTotal = infoMapper.getCaseInfoTotal(caseId);
        Integer resultTotal = caseResultMapper.getCaseResultTotal(resultId);
        return infoTotal == resultTotal ? true : false;
    }

    /**
     * 执行具体的caseRow
     */
    public String execCaseRow(JSONObject execContent) throws SQLException {
        String executeRequirement = execContent.get("executeRequirement").toString();
        String dbName = execContent.get("dbName").toString();
        String tableName = execContent.get("tableName").toString();
        String execLorData = execContent.get("execLorData").toString();
        String actualResult = "";
        if (executeRequirement.toLowerCase().contains("mysql")) {
            // 查询当前行使用到的库连接信息
            TkCommonDbConfig mysqlConfig = getConfigInfo(dbName, "Mysql");
            log.info("【开始执行 mysql操作】=======================");
            if (executeRequirement.toLowerCase().contains("select")) {
                actualResult = JdbcUtil.execSelectResult(dbName, mysqlConfig.getDbIp(), mysqlConfig.getDbPort(), mysqlConfig.getDbUser(), mysqlConfig.getDbPassword(), execLorData);
            } else {
                JdbcUtil.execAction(dbName, mysqlConfig.getDbIp(), mysqlConfig.getDbPort(), mysqlConfig.getDbUser(), mysqlConfig.getDbPassword(), execLorData);
            }
        }
        if (executeRequirement.toLowerCase().contains("mongo")) {
            log.info("【开始执行 mongo操作】======================");
            // 查询mongo配置的连接信息
            TkCommonDbConfig mongoConfig = getConfigInfo("", "Mongo");
            execMongoAction(executeRequirement, dbName, tableName, execLorData, mongoConfig);
        }
        if (executeRequirement.toLowerCase().contains("wait")) {
            try {
                Thread.sleep(Integer.parseInt(execLorData));
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return actualResult;
    }

    /**
     * 封装计算结果
     */
    public String calculateResultWriteCase(JSONObject execContent, String actualResult) {
        if (StringUtils.isNotEmpty(actualResult)) {
            execContent.put("actualResult", actualResult);
            execContent.put("compareResult", execContent.get("expectedResults").toString().equals(actualResult) == true ? "pass" : "fail");
            String jsonString = JSON.toJSONString(execContent);
            return jsonString;
        }
        return JSON.toJSONString(execContent);
    }

    /**
     * 查询数据库配置信息
     */
    public TkCommonDbConfig getConfigInfo(String dbName, String type) throws SQLException {
        TkCommonDbConfig tkCommonDbConfig = dbConfigService.selectDbConfigByDbName(dbName, type);
        if (tkCommonDbConfig == null) {
            throw new SQLException("未查询到数据库信息，请前往数据库管理进行配置");
        }
        return tkCommonDbConfig;
    }


    /**
     * 处理mongo操作
     *
     * @param executeRequirement
     * @param dbName
     * @param tableName
     * @param execLorData
     * @param mongoConfig
     */
    public void execMongoAction(String executeRequirement, String dbName, String tableName, String execLorData, TkCommonDbConfig mongoConfig) {
        MongoUtil.getCollection(mongoConfig.getDbIp(), mongoConfig.getDbPort(), mongoConfig.getDbUser(), mongoConfig.getDbPassword(), mongoConfig.getDbName(), dbName, tableName);
        switch (executeRequirement) {
            case "MONGO_DELETE": {
                String[] split = execLorData.split(":");
                MongoUtil.deleteLikeFromMongo(dbName, tableName, split[0], split[1]);
                break;
            }
            case "MONGO_INSERT": {
                MongoUtil.insert(dbName, tableName, execLorData);
                break;
            }
            case "MONGO_SELECT": {
                break;
            }
        }
    }


    @Test
    public void test() {


    }

}
